package application.menu;

import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glTexCoord2f;
import static org.lwjgl.opengl.GL11.glVertex2i;

import java.io.Serializable;

import helpers.Text;
import interfaces.IDrawable;

import org.lwjgl.opengl.Display;
import org.newdawn.slick.Color;

import application.RunnableComponent;
import application.Window;
import application.messages.Message;
import application.messages.commands.MenuCommand;
import application.messages.commands.ReverseMenuCommand;
import data.DataManager;

/**
 * Implements game menu.
 * 
 * @author Tomas Zima, Drahomir Karchnak
 */
public class Menu extends RunnableComponent implements IDrawable, Serializable
{
	/**
	 * Constructor.
	 */
	public Menu()
	{
		//
	}
	
	/**
	 * Redraws menu.
	 */
	public void redraw()
	{
		// Menu will be drawn only if it is active
		if (isActive())
		{
			// Draw cool border
			drawBackgroundBorders();
			
			// According to opened submenu
			switch (subScreen)
			{
				// Not it submenu
				case 0:
					// Logo
					new Text(450, 100, "Voxelcraft", new Color(0.5f, 0.5f, 0.0f)).redraw();
					
					// Menu buttons
					Text t[] = new Text[6];
					t[0] = new Text(450, 200, "New game", new Color(0.0f, 0.0f, 0.0f));
					t[1] = new Text(450, 250, "Save game", new Color(0.0f, 0.0f, 0.0f));
					t[2] = new Text(450, 300, "Load game", new Color(0.0f, 0.0f, 0.0f));
					t[3] = new Text(450, 350, "Help", new Color(0.0f, 0.0f, 0.0f));
					t[4] = new Text(450, 400, "Authors", new Color(0.0f, 0.0f, 0.0f));
					t[5] = new Text(450, 450, "Exit", new Color(0.0f, 0.0f, 0.0f));
					
					// Color of highlighted item
					Color hiCol = new Color(0.5f, 0.0f, 0.0f);
					
					// Set this color for right menu button
					switch (selectedItemIndex)
					{
						case 0:
							t[0].setColor(hiCol);
							break;
							
						case 1:
							t[1].setColor(hiCol);
							break;
							
						case 2:
							t[2].setColor(hiCol);
							break;
							
						case 3:
							t[3].setColor(hiCol);
							break;
							
						case 4:
							t[4].setColor(hiCol);
							break;
						
						case 5:
							t[5].setColor(hiCol);
							break;
					}
					
					// Draw all buttons
					for (int i = 0; i < 6; i++)
					{
						t[i].redraw();
					}
					
					break;
					
				// Help
				case 1:
					new Text(450, 100, "Help", new Color(0.5f, 0.5f, 0.0f)).redraw();
					break;
					
				// Authors
				case 2:
					new Text(450, 100, "Authors", new Color(0.5f, 0.5f, 0.0f)).redraw();
					new Text(200, 200, "Drahomir Karchnak", new Color(0.5f, 0.1f, 0.1f)).redraw();
					new Text(300, 250, "bacil94 @ gmail.com", new Color(0.7f, 0.7f, 0.7f)).redraw();
					new Text(200, 300, "Tomas Zima", new Color(0.5f, 0.1f, 0.1f)).redraw();
					new Text(300, 350, "tomas.zima.66 @ gmail.com", new Color(0.7f, 0.7f, 0.7f)).redraw();
					break;
			}
		}
	}

	/**
	 * Draws cool border in background.
	 */
	private void drawBackgroundBorders()
	{
		// Make correct OpenGL settings
		Window.disableTexturing();
		Window.enableTexColorMixing();
		DataManager.getInstance().rebindMenuBackgroundQuad();
		
		// Start drawing
		glBegin(GL_QUADS);
			/*
			 * Left down
			 */
			glTexCoord2f(0, 1);
			glVertex2i(0,Display.getHeight()/2);
			
			glTexCoord2f(1, 1);
			glVertex2i(Display.getWidth()/2,Display.getHeight()/2);
			
			glTexCoord2f(1, 0);
			glVertex2i(Display.getWidth()/2,Display.getHeight());
			
			glTexCoord2f(0, 0);
			glVertex2i(0,Display.getHeight());
		
			/*
			 * Left up
			 */
			glTexCoord2f(0, 0);
			glVertex2i(0,0);
			
			glTexCoord2f(1, 0);
			glVertex2i(Display.getWidth()/2,0);
			
			glTexCoord2f(1, 1);
			glVertex2i(Display.getWidth()/2,Display.getHeight()/2);
			
			glTexCoord2f(0, 1);
			glVertex2i(0,Display.getHeight()/2);
			
			/*
			 * Right up
			 */
			glTexCoord2f(1, 0);
			glVertex2i(Display.getWidth()/2,0);

			glTexCoord2f(0, 0);
			glVertex2i(Display.getWidth(),0);
			
			glTexCoord2f(0, 1);
			glVertex2i(Display.getWidth(),Display.getHeight()/2);
			
			glTexCoord2f(1, 1);
			glVertex2i(Display.getWidth()/2,Display.getHeight()/2);

			/*
			 * Right down
			 */
			glTexCoord2f(1, 1);
			glVertex2i(Display.getWidth()/2,Display.getHeight()/2);

			glTexCoord2f(0, 1);
			glVertex2i(Display.getWidth(),Display.getHeight()/2);
			
			glTexCoord2f(0, 0);
			glVertex2i(Display.getWidth(),Display.getHeight());
			
			glTexCoord2f(1, 0);
			glVertex2i(Display.getWidth()/2,Display.getHeight());
		glEnd();
		
		// Set OpenGL settings back to default
		Window.disableTexColorMixing();
		Window.enableTexturing();
	}
	
	/**
	 * Called when menu is activated.
	 */
	@Override
	protected void onActivation()
	{
		//
	}

	/**
	 * Called when menu is deactivated.
	 */
	@Override
	protected void onDeactivation()
	{
		//
	}
	
	/**
	 * Enter new message to the menu.
	 * 
	 * @param message
	 */
	@Override
	public void enterNewMessage(Message message)
	{
		// This is protection before too fast movement in menu 
		if (lastUserInput + 100 < System.currentTimeMillis())
		{
			// Perform action based on command
			switch ((MenuCommand) message.command)
			{
				// Select item in the way down
				case SELECT_DOWN:
					if (selectedItemIndex == 5)
					{
						selectedItemIndex = 0;
						break;
					}
					selectedItemIndex++;
					break;
					
				// Select item in the way up
				case SELECT_UP:
					if (selectedItemIndex == 0)
					{
						selectedItemIndex = 5;
						break;
					}
					selectedItemIndex--;
					
					break;
					
				// Open submenu or perform an action
				// (this is called usually when user press ENTER)
				case SELECT_ITEM:
					// Check internal index of item and prepare ReverseMenuCommand
					// to actually call this operation
					switch (selectedItemIndex)
					{
						case 0:
							menuCommand = ReverseMenuCommand.NEW_GAME;
							break;
						
						case 1:
							menuCommand = ReverseMenuCommand.SAVE_GAME;
							break;
							
						case 2:
							menuCommand = ReverseMenuCommand.LOAD_GAME;
							break;
							
						case 3:
							menuCommand	= ReverseMenuCommand.HELP;
							subScreen	= 1;
							break;
							
						case 4:
							menuCommand	= ReverseMenuCommand.AUTHORS;
							subScreen	= 2;
							break;
							
						case 5:
							menuCommand = ReverseMenuCommand.EXIT;
							break;
					}
					break;
					
				default:
					break;
			}
			
			// Part of protection before too fast cursor movement 
			lastUserInput = System.currentTimeMillis();
		}
	}
	
	/**
	 * Returns current action. After executing the action,
	 * call clearMenuCommand().
	 * 
	 * @return
	 */
	public ReverseMenuCommand getAction()
	{
		return menuCommand;
	}
	
	/**
	 * Clear current action. It is necessary to call this
	 * immediately after reading the action, because in the
	 * other case, the action will be started multiple times.
	 */
	public void clearMenuCommand()
	{
		this.menuCommand = ReverseMenuCommand.NONE;
	}
	
	/**
	 * Checks if some subscreen is activated or not.
	 * 
	 * @return
	 */
	public boolean isSubScreenActivated()
	{
		if (subScreen == 0)
		{
			// Main page of menu
			return false;
		}
		else
		{
			// Other page of menu
			return true;
		}
	}

	/**
	 * Go back to main menu.
	 */
	public void goOutOfSubScreen()
	{
		subScreen = 0;
	}
	
	// Used for navigating in menu
	private int					selectedItemIndex	= 0;
	private int					subScreen			= 0;

	// Used for slowing down the cursor
	private long				lastUserInput		= System.currentTimeMillis();
	
	// Last command which should be executed by owner of menu (Application)
	private ReverseMenuCommand	menuCommand			= ReverseMenuCommand.NONE;
}
